package website.haicheng.server.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import website.haicheng.server.common.constant.AttrConstant;
import website.haicheng.server.model.dto.MessageDto;
import website.haicheng.server.model.vo.Resp;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: 582895699@qq.com
 * @Desctription: channel管理
 * @Date: Created in 2021/12/1 16:40
 */
@Slf4j
@Component
public class NettyManage {

    /**
     * channel关系映射
     */
    public Map<ChannelId, Channel> channelMap = new ConcurrentHashMap<>();
    /**
     * 用户-channel关系映射
     */
    public Map<String, ChannelId> userChannelMap = new ConcurrentHashMap<>();

    /**
     * 保存channel关联关系
     *
     * @param ch
     */
    public void addChannel(Channel ch) {
        channelMap.put(ch.id(), ch);
    }

    /**
     * 保存账号和channel的映射关系
     *
     * @param account account
     * @param ch      ch
     */
    public void addUser(String account, Channel ch) {
        userChannelMap.put(account, ch.id());
    }

    /**
     * 移除管理关系
     *
     * @param ch
     * @param account
     */
    public void remove(Channel ch, String account) {
        channelMap.remove(ch.id());
        userChannelMap.remove(account);
    }

    /**
     * 判断是否已经登录
     *
     * @param account 账号
     * @return
     */
    public boolean alreadyLogin(String account) {
        return userChannelMap.containsKey(account);
    }

    /**
     * 群发或点对点发送消息
     *
     * @param dto MessageDto
     */
    public void send(MessageDto dto) {
        String receiver = dto.getReceiver();
        if (StrUtil.isNotBlank(receiver)) {
            ChannelId channelId = userChannelMap.get(receiver);
            if (Objects.isNull(channelId)) {
                // 处理离线消息
                log.info("客户端[{}]离线，执行离线消息",receiver);
                return;
            }
            Channel channel = channelMap.get(channelId);
            String account = channel.attr(AttrConstant.ATTRIBUTE_KEY_ACCOUNT).get();
            log.info("向用户[{}]发送消息[{}]", account, dto.getData());
            channel.writeAndFlush(Resp.ok(dto.getData()));
            return;
        }

        Collection<Channel> channels = channelMap.values();
        if (CollUtil.isEmpty(channels)) {
            log.info("客户端全部离线，执行离线消息");
            return;
        }

        for (Channel channel : channels) {
            if (!channel.isActive()) {
                // 处理离线消息
                log.info("客户端离线，执行离线消息");
                continue;
            }
            String account = channel.attr(AttrConstant.ATTRIBUTE_KEY_ACCOUNT).get();
            log.info("向用户[{}]发送消息[{}]", account, dto.getData());
            channel.writeAndFlush(Resp.ok(dto.getData()));
        }
    }
}
